import { ref, shallowRef, isRef } from 'vue';
import newForm from '../entity/Form';
import extentContext from '../context.js';

/**
 * 表格助手
 * 提供公共获取列表，分页，排序，查询，打开窗口等方法
 * 
 * @param {Object} options 配置参数
 * @param {ApiEntity | Object} options.api * 接口对象，如果对象是ApiEntity实例，则直接使用，已包含context,page,deleteById
 * 
 * @param {Object} options.api.context * 接口上下文对象
 * @param {Function} options.api.page * 分页接口
 * @param {Function} options.api.deleteById * 删除接口
 * 
 * @param {Object | Ref} options.page 分页参数，默认为{pageNum:1,pageSize:10}
 * 
 * @param {Boolean} options.autoGetList 是否初始化时获取列表，默认为true
 * @param {Object} options.refs 组件引用
 * @param {Object} options.refs.editRef 编辑组件引用
 * 
 * @param {Array} options.sort 默认排序，与element-plus的排序一致
 * @param {Object | Ref} options.queryParams 默认请求参数
 * 
 * @param {Function} options.onGetDataAfter 查询数据之后，参数config，可对config进行修改
 * @param {Function} options.onGetDataBefore 获取查询参数之前，参数config，可对config进行修改
 * @param {Function} options.onGetDataError 错误回调
 * @param {Function} options.onDeleteRowAfter 删除后
 * 
 */
export default class TableHelper{

  api = {
    context: null,
  }; //Api
  queryParams = ref({
    queryParams: {}
  }); // 查询参数
  tips = Object.assign({}, TIPS); // 提示
  sort = null;
  page = ref({ // 分页
    total: 0,
    pageNum: 1,
    pageSize: 10
  });
  loading = shallowRef(false); // 等待加在
  tableData = ref([]);// 表格数据
  rowContextmenu = []; // 右键菜单

  _defaultValie= {};

  refs = {};

  onGetDataAfter = null; // 查询数据之前
  onGetDataBefore = null; // 获取查询参数之后
  onGetDataError = null; // 错误回调
  onDeleteRowAfter = null; // 删除后


  constructor(options){
    let self = this;
    let opt = Object.assign({
      autoGetList: true,
    }, options);

    self.refs = opt.refs || {};

    self.api.context = opt.api;
    self.api.page = opt.api.page;
    self.api.deleteById = opt.api.deleteById;
    self.sort = opt.sort;

    if (isRef(opt.page)){
      self.page = opt.page;
    } else {
      Object.assign(self.page.value, opt.page);
    }

    if (isRef(opt.queryParams)){
      self.queryParams = opt.queryParams;
    } else {
      Object.assign(self.queryParams.value, opt.queryParams);
    }

    Object.assign(self.tips, opt.tips);
    

    self._defaultValie.queryParams = JSON.copy(self.queryParams.value);
    self._defaultValie.page = JSON.copy(self.page.value);
    self._defaultValie.sort = JSON.copy(self.sort);


    self.onGetDataBefore = opt.onGetDataBefore;
    self.onGetDataAfter = opt.onGetDataAfter;
    self.onGetDataError = opt.onGetDataError;
    self.onDeleteRowAfter = opt.onDeleteRowAfter;

    if (options.getId instanceof Function) {
      self.getId = options.getId;
    }

    // onMounted(()=>{
    //   let ins = getCurrentInstance();
    //   if (!self._tableRef){
    //     self._tableRef = ins.refs?.tableRef;
    //   }
    // });

    if (opt.autoGetList){
      self.getTableList();
    }

    // 构造器返回一个代理对象
    return new Proxy(this, {
      get(target, propKey, /* receiver */) {
        let val = target[propKey];
        if (val instanceof Function) {
          return function (...arg) {
            return val.apply(target, arg);
          };
        } else {
          return val;
        }
      }
    });
  }

  getId(form) {
    return form.id;
  }

  getTablQueryParams(){
    let self = this;
    let param = newForm(self.queryParams.value, {
      queryParams: {
        pageNum: self.page.value.pageNum,
        pageSize: self.page.value.pageSize,
      }
    });
    if (self.sort) {
      param.queryParams.sort = self.sort;
    }
    return param;
  }

  resetQueryParams(){
    let self = this;
    self.queryParams.value = JSON.copy(self._defaultValie.queryParams);
    self.page.value = JSON.copy(self._defaultValie.page);
    self.sort = JSON.copy(self._defaultValie.sort);

    self.getTableList();
  }

  /**
   * 获取表格参数
   */
  getTableList(){
    let self = this;
    if (!self){
      console.error('请使用 tableHelper.getTableList() 调用');
      return;
    }
    let func = self.api.page;
    
    self.loading.value = true;

    let queryParams = self.getTablQueryParams();

    let config = {
      queryParams,
      formOptions: {},
      getDataFunc: func,
      continue: true // 是否继续请求
    };

    if (self.onGetDataBefore instanceof Function){
      self.onGetDataBefore(config);
      if (!config.continue){
        return;
      }
    }

    if (!config.getDataFunc) {
      throw new Error('找不到获取列表的方法，请设置{options.api.page}或检查{options.api}');
    }

    // 条件为空则删除
    let params = config.queryParams.queryParams;
    if (params && !(params.conditions && params.conditions.length)) {
      delete params.conditions;
    }
    
    config.getDataFunc.call(self.api.context, config.queryParams, config.formOptions).then(res=>{
      config.res = res;
      let page = self.page.value;
      if (self.onGetDataAfter instanceof Function) {
        self.onGetDataAfter(config);
        if (!config.continue) {
          return;
        }
      }

      res = config.res;

      self.tableData.value = res.records;
      page.total = parseInt(res.total);
      return res;
    }).catch(err => {
      self.tableData.value = [];
      if (err instanceof Error){
        self.tips.emptyText = '错误';
      } else {
        self.tips.emptyText = err.data ? err.data.message : '错误';
      }
      self.onGetDataError && self.onGetDataError(err);
      throw err;
    }).finally(() => {
      self.loading.value = false;
    });
  }

  /**
   * 打开编辑窗口
   */
  openEdit(row, ...args){
    let data = row;
    if (data instanceof Event) {
      data = null;
    }

    if (this.refs.editRef?.value) {
      this.refs.editRef.value.show(data, ...args);
    } else {
      console.warn('找不到编辑窗口');
    }

  }


  /**
       * 打开删除提示
       * @param {Object} row 
       */
  deleteRow(row, ops) {
    let self = this;

    // 提示是否确认删除
    extentContext().message.confirm(self.tips.deleteRow.format3(row), '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    }).then(() => {
      self.api.deleteById.call(self.api.context, self.getId(row), ops).then(() => {
        extentContext().message.alert.success('删除成功');
        self.tableData.value.removeByAttr({ id: self.getId(row) });
        self.onDeleteRowAfter && self.onDeleteRowAfter(row);
      });
    });
  }


  get defaultSort() {
    return this.sort ? this.sort[0] : null;
  }
  sortChange(data) {
    if (data.order){
      let sort = { prop: data.prop, order: data.order };
      if(this.sort){
        this.sort[0] = sort;
      } else {
        this.sort = [sort];
      }
    } else {
      this.sort = null;
    }

    this.getTableList();
  }


}

const TIPS = Object.freeze({
  deleteRow: '是否确认删除此记录？',
});
